home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UNIXTOOL / M4SRC / _files / _M4 / Expr._C < prev    next >
Encoding:
Text File  |  1989-10-12  |  12.1 KB  |  588 lines

  1. /*
  2.  * expr.c
  3.  * Facility: m4 macro processor
  4.  * by: oz
  5.  */
  6.  
  7. #include <stdio.h>
  8.  
  9. /*
  10.  *      expression evaluator: performs a standard recursive
  11.  *      descent parse to evaluate any expression permissible
  12.  *      within the following grammar:
  13.  *
  14.  *      expr    :       query EOS
  15.  *      query   :       lor
  16.  *              |       lor "?" query ":" query
  17.  *      lor     :       land { "||" land }
  18.  *      land    :       bor { "&&" bor }
  19.  *      bor     :       bxor { "|" bxor }
  20.  *      bxor    :       band { "^" band }
  21.  *      band    :       eql { "&" eql }
  22.  *      eql     :       relat { eqrel relat }
  23.  *      relat   :       shift { rel shift }
  24.  *      shift   :       primary { shop primary }
  25.  *      primary :       term { addop term }
  26.  *      term    :       unary { mulop unary }
  27.  *      unary   :       factor
  28.  *              |       unop unary
  29.  *      factor  :       constant
  30.  *              |       "(" query ")"
  31.  *      constant:       num
  32.  *              |       "'" CHAR "'"
  33.  *      num     :       DIGIT
  34.  *              |       DIGIT num
  35.  *      shop    :       "<<"
  36.  *              |       ">>"
  37.  *      eqlrel  :       "="
  38.  *              |       "=="
  39.  *              |       "!="
  40.  *      rel     :       "<"
  41.  *              |       ">"
  42.  *              |       "<="
  43.  *              |       ">="
  44.  *
  45.  *
  46.  *      This expression evaluator is lifted from a public-domain
  47.  *      C Pre-Processor included with the DECUS C Compiler distribution.
  48.  *      It is hacked somewhat to be suitable for m4.
  49.  *
  50.  *      Originally by:  Mike Lutz
  51.  *                      Bob Harper
  52.  */
  53.  
  54. #define TRUE    1
  55. #define FALSE   0
  56. #define EOS     (char) 0
  57. #define EQL     0
  58. #define NEQ     1
  59. #define LSS     2
  60. #define LEQ     3
  61. #define GTR     4
  62. #define GEQ     5
  63. #define OCTAL   8
  64. #define DECIMAL 10
  65.  
  66. static char *nxtch;     /* Parser scan pointer */
  67.  
  68.  
  69. static int band (void);
  70. static int bor (void);
  71. static int bxor (void);
  72. static int constant (void);
  73. static int eql (void);
  74. static void experr (char *msg);
  75. static int factor (void);
  76. static int geteql (void);
  77. static int getrel (void);
  78. static int land (void);
  79. static int lor (void);
  80. static int num (void);
  81. static int primary (void);
  82. static int query (void);
  83. static int relat (void);
  84. static int shift (void);
  85. static int skipws (void);
  86. static int term (void);
  87. static int unary (void);
  88.  
  89. /*
  90.  * For longjmp
  91.  */
  92.  
  93. #include <setjmp.h>
  94.  
  95. static jmp_buf  expjump;
  96.  
  97. /*
  98.  * macros:
  99.  *
  100.  *      ungetch - Put back the last character examined.
  101.  *      getch   - return the next character from expr string.
  102.  */
  103. #define ungetch()       nxtch--
  104. #define getch()         *nxtch++
  105.  
  106. int expr (char *expbuf)
  107. {
  108.         register int rval;
  109.  
  110.         nxtch = expbuf;
  111.         if (setjmp(expjump) != 0)
  112.                 return (FALSE);
  113.         rval = query();
  114.         if (skipws() != EOS)
  115.             experr("Ill-formed expression");
  116.         return(rval);
  117. }
  118.  
  119. /*
  120.  * query : lor | lor '?' query ':' query
  121.  *
  122.  */
  123. static int query (void)
  124. {
  125.         register int bool, true_val, false_val;
  126.  
  127.         bool = lor();
  128.         if (skipws() != '?') {
  129.                 ungetch();
  130.                 return(bool);
  131.         }
  132.  
  133.         true_val = query();
  134.         if (skipws() != ':')
  135.                 experr("Bad query");
  136.  
  137.         false_val = query();
  138.         return(bool ? true_val : false_val);
  139. }
  140.  
  141. /*
  142.  * lor : land { '||' land }
  143.  *
  144.  */
  145. static int lor (void)
  146. {
  147.         register int c, vl, vr;
  148.  
  149.         vl = land();
  150.         while ((c = skipws()) == '|' && getch() == '|') {
  151.                 vr = land();
  152.                 vl = vl || vr;
  153.         }
  154.  
  155.         if (c == '|')
  156.                 ungetch();
  157.         ungetch();
  158.         return(vl);
  159. }
  160.  
  161. /*
  162.  * land : bor { '&&' bor }
  163.  *
  164.  */
  165. static int land (void)
  166. {
  167.         register int c, vl, vr;
  168.  
  169.         vl = bor();
  170.         while ((c = skipws()) == '&' && getch() == '&') {
  171.                 vr = bor();
  172.                 vl = vl && vr;
  173.         }
  174.  
  175.         if (c == '&')
  176.                 ungetch();
  177.         ungetch();
  178.         return(vl);
  179. }
  180.  
  181. /*
  182.  * bor : bxor { '|' bxor }
  183.  *
  184.  */
  185. static int bor (void)
  186. {
  187.         register int vl, vr, c;
  188.  
  189.         vl = bxor();
  190.         while ((c = skipws()) == '|' && getch() != '|') {
  191.                 ungetch();
  192.                 vr = bxor();
  193.                 vl |= vr;
  194.         }
  195.  
  196.         if (c == '|')
  197.                 ungetch();
  198.         ungetch();
  199.         return(vl);
  200. }
  201.  
  202. /*
  203.  * bxor : band { '^' band }
  204.  *
  205.  */
  206. static int bxor (void)
  207. {
  208.         register int vl, vr;
  209.  
  210.         vl = band();
  211.         while (skipws() == '^') {
  212.                 vr = band();
  213.                 vl ^= vr;
  214.         }
  215.  
  216.         ungetch();
  217.         return(vl);
  218. }
  219.  
  220. /*
  221.  * band : eql { '&' eql }
  222.  *
  223.  */
  224. static int band (void)
  225. {
  226.         register int vl, vr, c;
  227.  
  228.         vl = eql();
  229.         while ((c = skipws()) == '&' && getch() != '&') {
  230.                 ungetch();
  231.                 vr = eql();
  232.                 vl &= vr;
  233.         }
  234.  
  235.         if (c == '&')
  236.                 ungetch();
  237.         ungetch();
  238.         return(vl);
  239. }
  240.  
  241. /*
  242.  * eql : relat { eqrel relat }
  243.  *
  244.  */
  245. static int eql (void)
  246. {
  247.         register int vl, vr, rel;
  248.  
  249.         vl = relat();
  250.         while ((rel = geteql()) != -1) {
  251.                 vr = relat();
  252.  
  253.                 switch (rel) {
  254.  
  255.                 case EQL:
  256.                         vl = (vl == vr);
  257.                         break;
  258.                 case NEQ:
  259.                         vl = (vl != vr);
  260.                         break;
  261.                 }
  262.         }
  263.         return(vl);
  264. }
  265.  
  266. /*
  267.  * relat : shift { rel shift }
  268.  *
  269.  */
  270. static int relat (void)
  271. {
  272.         register int vl, vr, rel;
  273.  
  274.         vl = shift();
  275.         while ((rel = getrel()) != -1) {
  276.  
  277.                 vr = shift();
  278.                 switch (rel) {
  279.  
  280.                 case LEQ:
  281.                         vl = (vl <= vr);
  282.                         break;
  283.                 case LSS:
  284.                         vl = (vl < vr);
  285.                         break;
  286.                 case GTR:
  287.                         vl = (vl > vr);
  288.                         break;
  289.                 case GEQ:
  290.                         vl = (vl >= vr);
  291.                         break;
  292.                 }
  293.         }
  294.         return(vl);
  295. }
  296.  
  297. /*
  298.  * shift : primary { shop primary }
  299.  *
  300.  */
  301. static int shift (void)
  302. {
  303.         register int vl, vr, c;
  304.  
  305.         vl = primary();
  306.         while (((c = skipws()) == '<' || c == '>') && c == getch()) {
  307.                 vr = primary();
  308.  
  309.                 if (c == '<')
  310.                         vl <<= vr;
  311.                 else
  312.                         vl >>= vr;
  313.         }
  314.  
  315.         if (c == '<' || c == '>')
  316.                 ungetch();
  317.         ungetch();
  318.         return(vl);
  319. }
  320.  
  321. /*
  322.  * primary : term { addop term }
  323.  *
  324.  */
  325. static int primary (void)
  326. {
  327.         register int c, vl, vr;
  328.  
  329.         vl = term();
  330.         while ((c = skipws()) == '+' || c == '-') {
  331.                 vr = term();
  332.                 if (c == '+')
  333.                         vl += vr;
  334.                 else
  335.                         vl -= vr;
  336.         }
  337.  
  338.         ungetch();
  339.         return(vl);
  340. }
  341.  
  342. /*
  343.  * <term> := <unary> { <mulop> <unary> }
  344.  *
  345.  */
  346. static int term (void)
  347. {
  348.         register int c, vl, vr;
  349.  
  350.         vl = unary();
  351.         while ((c = skipws()) == '*' || c == '/' || c == '%') {
  352.                 vr = unary();
  353.  
  354.                 switch (c) {
  355.                 case '*':
  356.                         vl *= vr;
  357.                         break;
  358.                 case '/':
  359.                         vl /= vr;
  360.                         break;
  361.                 case '%':
  362.                         vl %= vr;
  363.                         break;
  364.                 }
  365.         }
  366.         ungetch();
  367.         return(vl);
  368. }
  369.  
  370. /*
  371.  * unary : factor | unop unary
  372.  *
  373.  */
  374. static int unary (void)
  375. {
  376.         register int val, c;
  377.  
  378.         if ((c = skipws()) == '!' || c == '~' || c == '-') {
  379.                 val = unary();
  380.  
  381.                 switch (c) {
  382.                 case '!':
  383.                         return(! val);
  384.                 case '~':
  385.                         return(~ val);
  386.                 case '-':
  387.                         return(- val);
  388.                 }
  389.         }
  390.  
  391.         ungetch();
  392.         return(factor());
  393. }
  394.  
  395. /*
  396.  * factor : constant | '(' query ')'
  397.  *
  398.  */
  399. static int factor (void)
  400. {
  401.         register int val;
  402.  
  403.         if (skipws() == '(') {
  404.                 val = query();
  405.                 if (skipws() != ')')
  406.                         experr("Bad factor");
  407.                 return(val);
  408.         }
  409.  
  410.         ungetch();
  411.         return(constant());
  412. }
  413.  
  414. /*
  415.  * constant: num | 'char'
  416.  *
  417.  */
  418. static int constant (void)
  419. {
  420.         /*
  421.          * Note: constant() handles multi-byte constants
  422.          */
  423.  
  424.         register int    i;
  425.         register int    value;
  426.         register char   c;
  427.         int             v[sizeof (int)];
  428.  
  429.         if (skipws() != '\'') {
  430.                 ungetch();
  431.                 return(num());
  432.         }
  433.         for (i = 0; i < sizeof(int); i++) {
  434.                 if ((c = getch()) == '\'') {
  435.                         ungetch();
  436.                         break;
  437.                 }
  438.                 if (c == '\\') {
  439.                         switch (c = getch()) {
  440.                         case '0':
  441.                         case '1':
  442.                         case '2':
  443.                         case '3':
  444.                         case '4':
  445.                         case '5':
  446.                         case '6':
  447.                         case '7':
  448.                                 ungetch();
  449.                                 c = num();
  450.                                 break;
  451.                         case 'n':
  452.                                 c = 012;
  453.                                 break;
  454.                         case 'r':
  455.                                 c = 015;
  456.                                 break;
  457.                         case 't':
  458.                                 c = 011;
  459.                                 break;
  460.                         case 'b':
  461.                                 c = 010;
  462.                                 break;
  463.                         case 'f':
  464.                                 c = 014;
  465.                                 break;
  466.                         }
  467.                 }
  468.                 v[i] = c;
  469.         }
  470.         if (i == 0 || getch() != '\'')
  471.                 experr("Illegal character constant");
  472.         for (value = 0; --i >= 0;) {
  473.                 value <<= 8;
  474.                 value += v[i];
  475.         }
  476.         return(value);
  477. }
  478.  
  479. /*
  480.  * num : digit | num digit
  481.  *
  482.  */
  483. static int num (void)
  484. {
  485.         register int rval, c, base;
  486.         int ndig;
  487.  
  488.         base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
  489.         rval = 0;
  490.         ndig = 0;
  491.         while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
  492.                 rval *= base;
  493.                 rval += (c - '0');
  494.                 c = getch();
  495.                 ndig++;
  496.         }
  497.         ungetch();
  498.         if (ndig == 0)
  499.                 experr("Bad constant");
  500.         return(rval);
  501. }
  502.  
  503. /*
  504.  * eqlrel : '=' | '==' | '!='
  505.  *
  506.  */
  507. static int geteql (void)
  508. {
  509.         register int c1, c2;
  510.  
  511.         c1 = skipws();
  512.         c2 = getch();
  513.  
  514.         switch (c1) {
  515.  
  516.         case '=':
  517.                 if (c2 != '=')
  518.                         ungetch();
  519.                 return(EQL);
  520.  
  521.         case '!':
  522.                 if (c2 == '=')
  523.                         return(NEQ);
  524.                 ungetch();
  525.                 ungetch();
  526.                 return(-1);
  527.  
  528.         default:
  529.                 ungetch();
  530.                 ungetch();
  531.                 return(-1);
  532.         }
  533. }
  534.  
  535. /*
  536.  * rel : '<' | '>' | '<=' | '>='
  537.  *
  538.  */
  539. static int getrel (void)
  540. {
  541.         register int c1, c2;
  542.  
  543.         c1 = skipws();
  544.         c2 = getch();
  545.  
  546.         switch (c1) {
  547.  
  548.         case '<':
  549.                 if (c2 == '=')
  550.                         return(LEQ);
  551.                 ungetch();
  552.                 return(LSS);
  553.  
  554.         case '>':
  555.                 if (c2 == '=')
  556.                         return(GEQ);
  557.                 ungetch();
  558.                 return(GTR);
  559.  
  560.         default:
  561.                 ungetch();
  562.                 ungetch();
  563.                 return(-1);
  564.         }
  565. }
  566.  
  567. /*
  568.  * Skip over any white space and return terminating char.
  569.  */
  570. static int skipws (void)
  571. {
  572.         register char c;
  573.  
  574.         while ((c = getch()) <= ' ' && c > EOS)
  575.                 ;
  576.         return(c);
  577. }
  578.  
  579. /*
  580.  * Error handler - resets environment to eval(), prints an error,
  581.  * and returns FALSE.
  582.  */
  583. static void experr (char *msg)
  584. {
  585.         printf("mp: %s\n",msg);
  586.         longjmp(expjump, -1);          /* Force eval() to return FALSE */
  587. }
  588.